package com.behome.netty.netty_B.bean;


import cn.hutool.json.JSONObject;
import com.behome.common.utils.AsciiJudgement;
import com.behome.netty.common.ByteConventerKit;
import com.behome.netty.netty_B.enums.ReBackAnnotation;
import com.behome.netty.netty_B.enums.ReBackCmdType;
import com.behome.netty.common.enums.TerminalWorkStatus;
import com.behome.system.domain.TTerminalDetail;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Locale;

/**
 * 附录B参数查询
 */
@ReBackAnnotation(
        type = ReBackCmdType.QUERY_RESPONSE
)
@Slf4j
public class TerminalBParamQuery extends BusinessReBackBase {
    //结果代码
    private byte resultCode;
    //结果描述长度
    private short resultDescLength;
    //结果描述内容
    private byte[] resultDescContent;
    //查询参数个数
    private int queryParamNum;

    private TTerminalDetail terminalDetail;

    public TerminalBParamQuery() {
    }

    public void setResultCode(byte resultCode) {
        this.resultCode = resultCode;
    }

    public void setResultDescLength(short resultDescLength) {
        this.resultDescLength = resultDescLength;
    }

    public void setResultDescContent(byte[] resultDescContent) {
        this.resultDescContent = resultDescContent;
    }

    public void setQueryParamNum(int queryParamNum) {
        this.queryParamNum = queryParamNum;
    }

    public boolean validateBeforeSerialize() {
        return false;
    }

    public byte[] serialize() {
        return null;
    }

    public BusinessReBackBase deserialize(byte[] businessData) {
        if (businessData != null && businessData.length > 0) {
            terminalDetail = new TTerminalDetail();
            ByteBuffer byteBuffer = ByteBuffer.wrap(businessData);
            this.resultCode = byteBuffer.get();
            this.resultDescLength = byteBuffer.getShort();
            this.resultDescContent = new byte[this.resultDescLength];
            byteBuffer.get(resultDescContent);
            if (resultDescLength != 0) {
                log.info("查询参数上报结果描述长度:{} 结果描述:{}", this.resultDescLength, ByteConventerKit.bcdToStr(resultDescContent));
            }
            this.queryParamNum = byteBuffer.get();
            JSONObject unknownParams = new JSONObject();
            for (int i = 0; i < this.queryParamNum; i++) {
                byte flag = byteBuffer.get();
                byte paramLength = byteBuffer.get();
                byte[] paramContent = new byte[paramLength];
                byteBuffer.get(paramContent);
                switch (flag) {
                    case 0x01://音量
                        int volume = paramContent[0];
                        terminalDetail.setVolume(String.valueOf(volume));
                        break;
                    case 0x02://IP+子网+网关
                        ByteBuffer ipBuffer = ByteBuffer.wrap(paramContent);
                        if (12 == paramLength) {
                            byte[] ip = new byte[4];
                            byte[] mask = new byte[4];
                            byte[] gateway = new byte[4];
                            ipBuffer.get(ip);
                            ipBuffer.get(mask);
                            ipBuffer.get(gateway);
                            terminalDetail.setIp(ByteConventerKit.bytesToIpStr(ip));
                            terminalDetail.setMask(ByteConventerKit.bytesToIpStr(mask));
                            terminalDetail.setGateway(ByteConventerKit.bytesToIpStr(gateway));
                        }
                        break;
                    case 0x03://回传地址
                        try {
                            String rebackAddress = "";
                            switch (paramContent[0]) {
                                case 0x01://IP（4 字节）+端口（2 字节）
                                    byte[] b = new byte[6];
                                    System.arraycopy(paramContent, 1, b, 0, 6);
                                    ByteConventerKit.bytesToIpAndPortStr(b);
                                    break;
                                case 0x02://域名（n 字节）+端口（2 字节）
                                    byte[] domainNameByte = new byte[paramContent[1]];
                                    System.arraycopy(paramContent, 2, domainNameByte, 0, paramContent[1]);
                                    String domainName = new String(domainNameByte);
                                    byte[] portByte = new byte[2];
                                    System.arraycopy(paramContent, 2 + paramContent[1], portByte, 0, 2);
                                    String port = String.valueOf(ByteConventerKit.bytesToShort(portByte));
                                    rebackAddress = domainName + ":" + port;
                                    break;
                                case 0x03://短信号码的长度（通常为 11 个字节的数字）
                                    rebackAddress = ByteConventerKit.bytesToThinHexStr(paramContent);
                            }
                            terminalDetail.setRebackAddress(rebackAddress);
                        } catch (Exception e) {
                            log.error("回传地址解析异常:{}", e.getMessage());
                        }
                        break;
                    case 0x04://资源编码
                        String resourceCode = ByteConventerKit.deserializeResourceCode(paramContent);
                        terminalDetail.setResourceCode(resourceCode);
                        break;
                    case 0x05://物理地址
                        byte[] physicalByte = new byte[paramContent[0]];
                        System.arraycopy(paramContent, 1, physicalByte, 0, physicalByte.length);
                        ByteConventerKit.bcdToStr(physicalByte);
                        break;
                    case 0x06://终端状态
                        TerminalWorkStatus workStatus = TerminalWorkStatus.getEnumByValue(paramContent[0]);
                        break;
                    case 0x07://故障代码
                        byte faultCode = paramContent[0];
                        break;
                    case 0x08://设备类型
                        String deviceType = extracted(paramContent);
                        break;
                    case 0x09://硬件版本号
                        String hardwareVersion = extracted(paramContent);
                        terminalDetail.setHardVersion(hardwareVersion);
                        break;
                    case 0x0A://软件版本号
                        String softwareVersion = extracted(paramContent);
                        terminalDetail.setSoftVersion(softwareVersion);
                        break;
                    case 0x0B://调频信号状态
                        int fmSignalStrength = paramContent[0];
                        int fmSignalQuality = paramContent[1];
                        break;
                    case 0x0C://DVB信号状态
                        int dvbSignalStrength = paramContent[0];
                        int dvbSignalQuality = paramContent[1];
                        break;
                    case 0x0D://DTMB信号状态
                        int dtmbSignalStrength = paramContent[0];
                        int dtmbSignalQuality = paramContent[1];
                        break;
                    case 0x0E://有线频率
                        String wiredFrequency = "";
                        try {
                            byte[] wiredFrequencyByte = new byte[4];
                            System.arraycopy(paramContent, 0, wiredFrequencyByte, 0, 4);
                            wiredFrequency = ByteConventerKit.bytesToInt2(wiredFrequencyByte, 0) + ",";
                            byte[] codingRate = new byte[4];
                            System.arraycopy(paramContent, 4, codingRate, 0, 4);
                            wiredFrequency += ByteConventerKit.bytesToInt2(codingRate, 0) + ",";
                            byte[] qam = new byte[1];
                            System.arraycopy(paramContent, 8, qam, 0, 1);
                            wiredFrequency += String.format("%d", qam[0]);
                        } catch (Exception e) {
                            wiredFrequency = "未知";
                        }
                        terminalDetail.setDvbcFreq(wiredFrequency);
                        break;
                    case 0x0F://地面无线频率;
                        String dtmbFrequency = "";
                        try {
                            dtmbFrequency = String.valueOf(ByteConventerKit.bytesToInt2(paramContent, 0));
                        } catch (Exception e) {
                            dtmbFrequency = "未知";
                        }
                        terminalDetail.setDtmbFreq(dtmbFrequency);
                        break;
                    case 0x10://FM频点扫描列表;
                        String fmList = "";
                        try {
                            String fmListHexStr = ByteConventerKit.bytesToHexStr(paramContent, false);
                            fmList = ByteConventerKit.to_FmScanFrelist(fmListHexStr);
                        } catch (Exception e) {
                            fmList = "未知";
                        }
                        terminalDetail.setFmList(fmList);
                        break;
                    case 0x11://FM当前频点
                        byte[] commandFrequencyByte = new byte[3];
                        System.arraycopy(paramContent, 0, commandFrequencyByte, 0, 3);
                        String commandFrequency = Integer.parseInt(ByteConventerKit.bytesToHexStr(commandFrequencyByte, false)) + "";
                        byte[] contentFrequencyByte = new byte[3];
                        System.arraycopy(paramContent, 3, contentFrequencyByte, 0, 3);
                        String contentFrequency = Integer.parseInt(ByteConventerKit.bytesToHexStr(contentFrequencyByte, false)) + "";
                        terminalDetail.setFm(commandFrequency + "," + contentFrequency);
                        break;
                    case 0x12:
                        //FM维持指令模式;
                        try {
                            int fmKeepMode = paramContent[0];
                            byte[] fmKeepCycleByte = new byte[2];
                            System.arraycopy(paramContent, 1, fmKeepCycleByte, 0, 2);
                            int fmKeepCycle = Integer.parseInt(ByteConventerKit.bytesToThinHexStr(fmKeepCycleByte));
                            terminalDetail.setFmMode(String.valueOf(fmKeepMode));
                        } catch (Exception ignored) {

                        }
                        break;
                    default:
                        unknownParams.putOnce(ByteConventerKit.byteToHex(flag),ByteConventerKit.bytesToHexStr(paramContent, false));
                        break;
                }
            }
            log.debug("未知参数类型:{}", unknownParams);
            return this;
        } else {
            return null;
        }
    }

    //判断厂家指定义的东西是否为字符串还是BCD
    private static String extracted(byte[] content) {
        String s = "";
        boolean flag = false;
        try {
            for (byte b : content) {
                byte[] judgement = new byte[]{b};
                String temp = ByteConventerKit.bytesToHexStr(judgement, false);
                if (!AsciiJudgement.map.containsKey(temp.toUpperCase(Locale.ROOT))) {
                    flag = false;
                    break;
                }
                flag = true;
            }
            if (flag) {
                s = new String(content, StandardCharsets.US_ASCII);
            } else {
                s = ByteConventerKit.bcdToStr(content);
            }
        } catch (Exception e) {
            s = "未知";
        }
        return s;
    }

    public String toCHJsonString() {
        String result = "";
        switch (this.resultCode) {
            case 0:
                result = "终端成功接收并且正确处理";
                break;
            case 13:
                result = "请求数据包出现错误";
                break;
            case 60:
                result = "终端出现错误，无法处理";
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.putOnce("结果代码",result);
        jsonObject.putOnce("结果描述内容","");
        jsonObject.putOnce("参数个数",this.queryParamNum);
        jsonObject.putOnce("参数",terminalDetail);
        return jsonObject.toString();
    }

}
